home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / gfx / show / swfplayersrc.lha / Lib / sound.cc < prev    next >
C/C++ Source or Header  |  2002-11-05  |  16KB  |  757 lines

  1. /////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998,1999 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //
  22. #include "swf.h"
  23.  
  24. #ifndef NOSOUND
  25. #ifndef AMIGA
  26. #include <unistd.h>
  27. #include <fcntl.h>
  28. #include <sys/ioctl.h>
  29. #include <linux/soundcard.h>
  30. #else
  31. /* Amiga includes */
  32. extern "C" {
  33. #include <clib/alib_protos.h>
  34.  
  35. #ifdef __PPC__
  36. #define DOS_DOSEXTENS_H
  37. #include </ADE/os-includeppc/proto/dos.h>
  38. #undef DOS_DOSEXTENS_H
  39. #include </ADE/os-includeppc/proto/exec.h>
  40. #else
  41. #include <clib/exec_protos.h>
  42. #endif
  43. #include <devices/audio.h>
  44. #include <exec/memory.h>
  45. #include <graphics/gfxbase.h>
  46. }
  47.  
  48. struct channel_info {
  49.   struct MsgPort *audio_mp;
  50.   struct IOAudio *audio_io;
  51.   BOOL sound_in_progress;
  52. };
  53.  
  54. static struct channel_info channel_info[2] =
  55. {
  56.   {FALSE, NULL, NULL},
  57.   {FALSE, NULL, NULL},
  58. };
  59.  
  60. static struct MsgPort *audio_mp = NULL;
  61. static struct IOAudio *audio_io = NULL;
  62. static BOOL audio_is_open = FALSE;
  63.  
  64. extern struct GfxBase *GfxBase;
  65. static ULONG clock_constant;
  66. static ULONG amiga_period;
  67. static UBYTE sound_in_progress = 0;
  68. #endif // !AMIGA
  69. #endif // !NOSOUND
  70.  
  71. #ifdef RCSID
  72. static char *rcsid = "$Id: sound.cc,v 1.11 1999/01/31 21:14:22 olivier Exp $";
  73. #endif
  74. #define PRINT 0
  75.  
  76. //////////// SOUND
  77.  
  78. Sound::Sound(long id) : Character(SoundType, id)
  79. {
  80.     samples = 0;
  81.     stereo = 0;
  82.     soundRate = 0;
  83.     sampleSize = 1;
  84. }
  85.  
  86. Sound::~Sound()
  87. {
  88.     if (samples) {
  89.         delete samples;
  90.     }
  91. }
  92.  
  93. void
  94. Sound::setSoundFlags(long f) {
  95.     switch (GET_SOUND_RATE_CODE(f)) {
  96.         case 0:
  97.             soundRate = 5500;
  98.             break;
  99.         case 1:
  100.             soundRate = 11000;
  101.             break;
  102.         case 2:
  103.             soundRate = 22000;
  104.             break;
  105.         case 3:
  106.             soundRate = 44000;
  107.             break;
  108.     }
  109.     if (f & soundIs16bit) {
  110.         sampleSize = 2;
  111.     }
  112.     if (f & soundIsStereo) {
  113.         stereo = 1;
  114.     }
  115.  
  116. #if PRINT
  117.     printf("-----\nFlags = %2x\n", f);
  118.     printf("Rate = %d kHz  ", soundRate);
  119.     printf("SampleSize = %d byte(s) ", sampleSize);
  120.     if (f & soundIsStereo) {
  121.         printf("Stereo  ");
  122.     } else {
  123.         printf("Mono  ");
  124.     }
  125.     if (f & soundIsADPCMCompressed) {
  126.         printf("ADPCM\n");
  127.     } else {
  128.         printf("Raw\n");
  129.     }
  130. #endif
  131. }
  132.  
  133. char *
  134. Sound::setNbSamples(long n) {
  135.     long size;
  136.  
  137.     nbSamples = n;
  138.  
  139.     size = nbSamples * (stereo ? 2 : 1) * sampleSize;
  140.  
  141.     samples = new char[ size ];
  142.  
  143.     memset((char *)samples,0, size);
  144.  
  145.     return samples;
  146. }
  147.  
  148. long
  149. Sound::getRate() {
  150.     return soundRate;
  151. }
  152.  
  153. long
  154. Sound::getChannel() {
  155.     return stereo ? 2 : 1;
  156. }
  157.  
  158. long
  159. Sound::getNbSamples() {
  160.     return nbSamples;
  161. }
  162.  
  163. long
  164. Sound::getSampleSize() {
  165.     return sampleSize;
  166. }
  167.  
  168. char *
  169. Sound::getSamples() {
  170.     return samples;
  171. }
  172.  
  173. //////////// SOUND MIXER
  174.  
  175. long  SoundMixer::dsp = -1;    // Init of descriptor
  176. long  SoundMixer::blockSize = 0;    // Driver sound buffer size
  177. long  SoundMixer::nbInst = 0;    // Nb SoundMixer instances
  178. long  SoundMixer::sampleSize = 0;
  179. long  SoundMixer::stereo = 0;
  180. long  SoundMixer::soundRate = 0;
  181. char *SoundMixer::buffer = 0;
  182.  
  183. SoundMixer::SoundMixer(char *device)
  184. {
  185. #ifndef NOSOUND
  186. #ifdef AMIGA
  187.     dsp = -1;
  188.     audio_is_open = FALSE;
  189.     perror("Linux specific");
  190. #else
  191.     int status;
  192.     long fmt;
  193.  
  194.     list = 0;    // No sound to play
  195.  
  196.     if (nbInst++) {
  197.         // Device is already open
  198.         return;
  199.     }
  200.  
  201.     dsp = open(device,O_WRONLY);
  202.     if (dsp < 0) {
  203.         perror("open dsp");
  204.         return;
  205.     }
  206.  
  207.     // Reset device
  208.     status = ioctl(dsp, SNDCTL_DSP_RESET);
  209.     if (status < 0) perror("ioctl SNDCTL_DSP_RESET");
  210.  
  211.     // Set sample size
  212.     fmt = AFMT_S16_LE;
  213.     sampleSize = 2;
  214.     status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
  215.     if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");
  216.  
  217.     if (status) {
  218.         fmt = AFMT_U8;
  219.         sampleSize = 1;
  220.         status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
  221.         if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");
  222.     }
  223.  
  224.     // Set stereo channel
  225.     stereo = 1;
  226.     status = ioctl(dsp, SNDCTL_DSP_STEREO, &stereo);
  227.  
  228.     if (status) {
  229.         stereo = 0;
  230.     }
  231.  
  232.     // Set sound rate in Hertz
  233.     soundRate = 11000;
  234.  
  235.     status = ioctl(dsp, SNDCTL_DSP_SPEED, &soundRate);
  236.     if (status < 0) perror("ioctl SNDCTL_DSP_SPEED");
  237.  
  238.     // Get device buffer size
  239.     status = ioctl(dsp, SNDCTL_DSP_GETBLKSIZE, &blockSize);
  240.     if (status < 0) perror("ioctl SNDCTL_DSP_GETBLKSIZE");
  241.     if (blockSize < 1024) {
  242.         blockSize = 32768;
  243.     }
  244.     blockSize *= 2;
  245.  
  246.     buffer = (char *)malloc(blockSize);
  247.     if (buffer == 0) {
  248.         close(dsp);
  249.         dsp = -1;
  250.     }
  251.  
  252. #if PRINT
  253.     int caps;
  254.  
  255.     ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps);
  256.     printf("Audio capabilities = %x\n", caps);
  257.     printf("Sound Rate  = %d\n", soundRate);
  258.     printf("Stereo      = %d\n", stereo);
  259.     printf("Sample Size = %d\n", sampleSize);
  260.     printf("Buffer Size = %d\n", blockSize);
  261. #endif /* PRINT */
  262.  
  263. #endif    /* NOSOUND */
  264. #endif /* AMIGA */
  265. }
  266.  
  267.  
  268. SoundMixer::SoundMixer(int flags)
  269. {
  270. #ifndef NOSOUND
  271. #ifndef AMIGA
  272.     dsp = -1;
  273.     perror("Amiga specific");
  274. #else
  275.     int status;
  276.     long fmt;
  277.  
  278.     int i;
  279.     UBYTE MyChannels [] = {1,2,4,8};
  280.     UBYTE chans[1];
  281.     struct channel_info *c;
  282.  
  283.     buffer1 = (char *) NULL;
  284.     buffer2 = (char *) NULL;
  285.  
  286.     list = 0;    // No sound to play
  287.  
  288.     if (nbInst++) {
  289.         // Device is already open
  290.         return;
  291.     }
  292.  
  293.     if ((audio_mp = CreatePort (NULL, 0)) == NULL ||
  294.         (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  295.                 MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  296.     {
  297.         fprintf(stderr,"SoundInit error 1\n");
  298.         return;
  299.    }
  300.  
  301.     chans[0] = 3;
  302.  
  303.  
  304.     audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  305.     audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  306.     audio_io->ioa_AllocKey = 0;
  307.     audio_io->ioa_Data = chans;
  308.     audio_io->ioa_Length = sizeof(chans);
  309.  
  310.     if (OpenDevice((const char *) AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0) // [SHA, 03/10/2002 : PPC compilation]
  311.     {
  312.         #if PRINT
  313.         fprintf(stderr,"OpenDevice(\"audio.device\") failed.  Sound disabled.\n");
  314.         #endif
  315.         return;
  316.     }
  317.  
  318.     audio_is_open = TRUE;
  319.  
  320.  
  321.     for (i = 0; i < 2; i++)
  322.     {
  323.         c = &channel_info[i];
  324.         if ((c->audio_mp = CreatePort (NULL, 0)) == NULL ||
  325.             (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  326.             MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  327.         {
  328.             fprintf(stderr,"SoundInit error 2\n");
  329.             return;
  330.        }
  331.         *c->audio_io = *audio_io;
  332.         c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  333.         c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  334.     }
  335.  
  336.  
  337.     if ((GfxBase->DisplayFlags & NTSC) != 0)
  338.         clock_constant = 3579545;   /* NTSC */
  339.     else
  340.         clock_constant = 3546895;   /* PAL */
  341.  
  342.     dsp = 1;            /* pretend we've opened the Linux sound device... */
  343.  
  344.     // Set stereo channel
  345.     if (flags & AMIGAFLAG_MONO)
  346.         stereo = 0;                // mono sound
  347.     else
  348.         stereo = 1;                // stereo    
  349.  
  350.     // Set sound rate in Hertz
  351.     soundRate = 11000;
  352.     amiga_period = ((clock_constant << 1) + soundRate) / (((unsigned long) soundRate) << 1);
  353.  
  354.     blockSize = 64 * 1024;        /* 64K ??????????????? */
  355.  
  356.     if (stereo)
  357.     {
  358.         /* RESULT NOT CHECKED!! */
  359.         buffer1 = (char *) AllocVec(blockSize, MEMF_CHIP);
  360.         buffer2 = (char *) AllocVec(blockSize, MEMF_CHIP);
  361.         buffer = buffer1;
  362.     }
  363.     else
  364.     {
  365.         buffer = (char *) AllocVec(blockSize, MEMF_CHIP);
  366.     }    
  367.  
  368. #if PRINT
  369.     int caps;
  370.  
  371.     ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps);
  372.     printf("Audio capabilities = %x\n", caps);
  373.     printf("Sound Rate  = %d\n", soundRate);
  374.     printf("Stereo      = %d\n", stereo);
  375.     printf("Sample Size = %d\n", sampleSize);
  376.     printf("Buffer Size = %d\n", blockSize);
  377. #endif /* PRINT */
  378.  
  379. #endif    /* NOSOUND */
  380.  
  381. #endif /* AMIGA */
  382. }
  383.  
  384. #ifdef AMIGA
  385. void static AmigaStopSound(int handle)
  386. {
  387.     struct channel_info *c;
  388.  
  389.     if (channel_info[handle].sound_in_progress)
  390.     {
  391.         /* Set the volume to 0 before aborting the audio, else we'll get a 'click' */
  392. //        audio_io->ioa_Request.io_Command = ADCMD_PERVOL;
  393. //        audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  394. //        audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << handle);
  395. //        audio_io->ioa_Period = amiga_period;
  396. //        audio_io->ioa_Volume = 0;
  397. //        BeginIO ((struct IORequest *)audio_io);
  398. //        WaitPort (audio_mp);
  399. //        GetMsg (audio_mp);
  400.  
  401. /*
  402.     if (!CheckIO((struct IORequest *)channel_info[handle].audio_io))
  403.     {
  404.         printf("already playing.  Waiting\n");
  405.         WaitPort (channel_info[handle].audio_mp);  // clears signal & returns immediately
  406.         GetMsg (channel_info[handle].audio_mp);
  407. printf("finished\n");
  408.         channel_info[handle].sound_in_progress = FALSE;
  409.         return;
  410.     }
  411.  
  412.         printf("Aborting\n");
  413. */
  414.  
  415.         AbortIO ((struct IORequest *)channel_info[handle].audio_io);
  416.         WaitPort (channel_info[handle].audio_mp);
  417.         GetMsg (channel_info[handle].audio_mp);
  418.         channel_info[handle].sound_in_progress = FALSE;
  419.     }
  420. }
  421. #endif
  422.  
  423. SoundMixer::~SoundMixer()
  424. {
  425. #ifndef AMIGA
  426.     if (--nbInst == 0) {
  427.         if (dsp > 0) {
  428.             close(dsp);
  429.             free(buffer);
  430.         }
  431.     }
  432. #else
  433.     int i;
  434.     if (--nbInst == 0)
  435.     {
  436.         if (audio_is_open)
  437.         {
  438.             for (i = 0; i < 2; i++) AmigaStopSound (i);
  439.             audio_io->ioa_Request.io_Unit = (struct Unit *) ((1 << 2) - 1);  /* free numChannels channels */
  440.             CloseDevice ((struct IORequest *)audio_io);
  441.             audio_is_open = FALSE;
  442.         }
  443.  
  444.         for (i = 0; i < 2; i++)
  445.         {
  446.             if (channel_info[i].audio_io != NULL)
  447.             {
  448.                 FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  449.                 channel_info[i].audio_io = NULL;
  450.             }
  451.             if (channel_info[i].audio_mp != NULL)
  452.             {
  453.                 DeletePort (channel_info[i].audio_mp);
  454.                 channel_info[i].audio_mp = NULL;
  455.             }
  456.         }
  457.  
  458.         if (audio_io != NULL)
  459.         {
  460.             FreeMem (audio_io, sizeof(struct IOAudio));
  461.             audio_io = NULL;
  462.         }
  463.         if (audio_mp != NULL)
  464.         {
  465.             DeletePort (audio_mp);
  466.             audio_mp = NULL;
  467.         }
  468.  
  469.         if (buffer1)
  470.         {
  471.             FreeVec(buffer1);
  472.             buffer1 = (char *) NULL;
  473.         }
  474.  
  475.         if (buffer2)
  476.         {
  477.             FreeVec(buffer2);
  478.             buffer2 = (char *) NULL;
  479.         }
  480.     }
  481. #endif
  482. }
  483.  
  484. void
  485. SoundMixer::stopSounds()
  486. {
  487. #ifndef NOSOUND
  488.     SoundList *sl,*del;
  489.  
  490.     for(sl = list; sl; ) {
  491.         del = sl;
  492.         sl = sl->next;
  493.         delete del;
  494.     }
  495.     list = 0;
  496. #endif
  497. }
  498.  
  499. void
  500. SoundMixer::startSound(Sound *sound)
  501. {
  502. #ifndef NOSOUND
  503.     SoundList *sl;
  504.  
  505.     if (sound) {
  506.         // Add sound in list
  507.         sl = new SoundList;
  508.         sl->rate = sound->getRate();
  509.         sl->stereo = (sound->getChannel() == 2);
  510.         sl->sampleSize = sound->getSampleSize();
  511.         sl->current = sound->getSamples();
  512.         sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel();
  513.         sl->next = list;
  514.         list = sl;
  515.     }
  516. #endif
  517. }
  518.  
  519. long
  520. SoundMixer::playSounds()
  521. {
  522. #ifndef NOSOUND
  523. #ifndef AMIGA
  524.     audio_buf_info     bufInfo;
  525. #endif
  526.     long         nbBytes, n;
  527.     SoundList    *sl,*prev;
  528.     int         status;
  529.  
  530.     // Init failed
  531.     if (dsp < 0) return 0;
  532.  
  533.     // No sound to play
  534.     if (list == 0) return 0;
  535.  
  536. #ifndef AMIGA
  537.     // Get free DMA buffer space
  538.     status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo);
  539.  
  540.     // Free space is not large enough to output data without blocking
  541.     // But there are still sounds to play. We must wait.
  542.     if (bufInfo.bytes < blockSize) return 1;
  543. #endif
  544.  
  545.     nbBytes = 0;
  546.  
  547.     // Fill buffer with silence.
  548.     memset((void*)buffer, 0, blockSize);
  549.  
  550.     prev = 0;
  551.     sl = list;
  552.     while(sl) {
  553.  
  554.         // Ask sound to fill the buffer
  555.         // according to device capabilities
  556.         n = fillSoundBuffer(sl, buffer, blockSize);
  557.  
  558.         // Remember the largest written size
  559.         if (n > nbBytes) {
  560.             nbBytes = n;
  561.         }
  562.  
  563.         // No more samples for this sound
  564.         if (sl->remaining == 0) {
  565.             // Remove sound from list
  566.             if (prev) {
  567.                 prev->next = sl->next;
  568.                 delete sl;
  569.                 sl = prev->next;
  570.             } else {
  571.                 list = sl->next;
  572.                 delete sl;
  573.                 sl = list;
  574.             }
  575.         } else {
  576.             sl = sl->next;
  577.         }
  578.     }
  579.  
  580.     if (nbBytes) {
  581. #ifndef AMIGA
  582.         // At last ! Play It !
  583.         write(dsp,buffer,nbBytes);
  584.         status = ioctl(dsp, SNDCTL_DSP_POST);
  585. #else
  586.         struct channel_info *c;
  587.         int ss;
  588.         UBYTE *lbuffer,*rbuffer;
  589.  
  590.         if (stereo)
  591.         {
  592.             ss = nbBytes >> 1;            /* buffer contains both the left & right channels, so the length is halved */
  593.             lbuffer = (UBYTE *) buffer;
  594.             rbuffer = (UBYTE *) buffer + (blockSize >> 1);
  595.         }
  596.         else
  597.         {
  598.             /* mono */
  599.             ss = nbBytes;
  600.             lbuffer = (UBYTE *) buffer;
  601.             rbuffer = (UBYTE *) buffer;
  602.         }
  603.  
  604. #if PRINT
  605.         printf("playing ladr=%p radr=%p len=%d (%d) stereo=%d\n",lbuffer,rbuffer,nbBytes, ss,stereo);
  606. #endif
  607.  
  608.         /* Wait for the sample to stop playing??? */
  609.         AmigaStopSound(0);
  610.         c = &channel_info[0];
  611.         c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  612.         c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  613.         c->audio_io->ioa_Data = lbuffer;
  614.         c->audio_io->ioa_Length = ss;
  615.         c->audio_io->ioa_Period = amiga_period;
  616.         c->audio_io->ioa_Volume = 63;
  617.         c->audio_io->ioa_Cycles = 1;
  618.         //BeginIO ((struct IORequest *)c->audio_io);
  619.           SendIO ((struct IORequest *)c->audio_io);
  620.  
  621.         c->sound_in_progress = TRUE;
  622.  
  623.         AmigaStopSound(1);
  624.         c = &channel_info[1];
  625.         c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  626.         c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  627.         c->audio_io->ioa_Data = rbuffer;
  628.         c->audio_io->ioa_Length = ss;
  629.         c->audio_io->ioa_Period = amiga_period;
  630.         c->audio_io->ioa_Volume = 63;
  631.         c->audio_io->ioa_Cycles = 1;
  632. //          BeginIO ((struct IORequest *)c->audio_io);
  633.           SendIO ((struct IORequest *)c->audio_io);
  634.         c->sound_in_progress = TRUE;
  635.  
  636.         if (stereo)
  637.         {
  638.             /* switch 'buffer' to point to the correct sound buffer */
  639.             if (buffer == buffer1)
  640.                 buffer = buffer2;
  641.             else
  642.                 buffer = buffer1;
  643.         }
  644. #endif
  645.     }
  646.  
  647.     return nbBytes;
  648. #else
  649.     return 0;
  650. #endif
  651. }
  652.  
  653. long
  654. SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize)
  655. {
  656.     long sampleLeft, sampleRight;
  657.     long skipOut, skipOutInit;
  658.     long skipIn, skipInInit;
  659.     long freqRatio;
  660.     long totalOut = 0;
  661.  
  662.     sampleLeft = sampleRight = 0;
  663.     skipOutInit = skipInInit = 0;
  664.  
  665.     freqRatio = sl->rate / soundRate;
  666.     if (freqRatio) {
  667.         skipOutInit = freqRatio - 1;
  668.         skipInInit = 0;
  669.     }
  670.  
  671.     freqRatio = soundRate / sl->rate;
  672.     if (freqRatio) {
  673.         skipInInit = freqRatio - 1;
  674.         skipOutInit = 0;
  675.     }
  676.  
  677.     skipOut = skipOutInit;
  678.     skipIn = skipInInit;
  679.     while (buffSize && sl->remaining) {
  680.         if (skipIn-- == 0) {
  681.             // Get sampleLeft
  682.             if (sl->sampleSize == 2) {
  683.                 sampleLeft = (long)(*(short *)(sl->current));
  684.                 if (sampleSize == 1) {
  685.                     sampleLeft = (sampleLeft >> 8) &0xff;
  686.                 }
  687.             } else {
  688.                 sampleLeft = (long)*(sl->current);
  689.                 if (sampleSize == 2) {
  690.                     sampleLeft <<= 8;
  691.                 }
  692.             }
  693.             sl->current += sl->sampleSize;
  694.             sl->remaining -= sl->sampleSize;
  695.  
  696.             if (sl->stereo) {
  697.                 // Get sampleRight
  698.                 if (sl->sampleSize == 2) {
  699.                     sampleRight = (long)(*(short *)(sl->current));
  700.                     if (sampleSize == 1) {
  701.                         sampleRight = (sampleRight >> 8) &0xff;
  702.                     }
  703.                 } else {
  704.                     sampleRight = (long)*(sl->current);
  705.                     if (sampleSize == 2) {
  706.                         sampleRight <<= 8;
  707.                     }
  708.                 }
  709.                 sl->current += sl->sampleSize;
  710.                 sl->remaining -= sl->sampleSize;
  711.  
  712.             } else {
  713.                 sampleRight = sampleLeft;
  714.             }
  715.             
  716.             skipIn = skipInInit;
  717.         }
  718.  
  719.         if (skipOut-- == 0) {
  720.             // Output
  721.             if (stereo) {
  722.                 if (sampleSize == 2) {
  723.                     *((short *)buff) += sampleLeft/2;
  724.                     buffSize -= sampleSize;
  725.                     buff += sampleSize;
  726.                     *((short *)buff) += sampleRight/2;
  727.                     buffSize -= sampleSize;
  728.                     buff += sampleSize;
  729.                 } else {
  730.                     *((char *)buff) += sampleLeft/2;
  731.                     buffSize -= sampleSize;
  732.                     buff += sampleSize;
  733.                     *((char *)buff) += sampleRight/2;
  734.                     buffSize -= sampleSize;
  735.                     buff += sampleSize;
  736.                 }
  737.                 totalOut += 2*sampleSize;
  738.             } else {
  739.                 if (sampleSize == 2) {
  740.                     *((short *)buff) += (sampleLeft+sampleRight)>>2;
  741.                     buffSize -= sampleSize;
  742.                     buff += sampleSize;
  743.                 } else {
  744.                     *((char *)buff) += (sampleLeft+sampleRight)>>2;
  745.                     buffSize -= sampleSize;
  746.                     buff += sampleSize;
  747.                 }
  748.                 totalOut += sampleSize;
  749.             }
  750.  
  751.             skipOut = skipOutInit;
  752.         }
  753.     }
  754.  
  755.     return totalOut;
  756. }
  757.